home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs20.d81 / fracland.sfx / fractal.hrland.c < prev   
Text File  |  1990-02-12  |  10KB  |  353 lines

  1. /* ╨ROGRAM: FRACTAL.HRLAND       ┴UTHOR: ╨AUL ╫. ├ARLSON
  2.  *
  3.  * ╘HIS PROGRAM PLOTS RANDOM FRACTAL LANDSCAPES IN HIRES
  4.  * MODE ON THE ├64.  ├OMPILED WITH THE ╨OWER ├ COMPILER.
  5.  */
  6.  
  7. #DEFINE ╠┴╬─   1
  8. #DEFINE ╫┴╘┼╥  2
  9. #DEFINE ╙╦┘    3
  10.  
  11. /* ╟LOBAL VARIABLES - ONLY MASK, COLOR, AND ODD ARE USED OUTSIDE OF
  12.  * THE MAIN FUNCTION.  ╘HE OTHERS ARE DECLARED GLOBAL FOR MEMORY
  13.  * ALLOCATION PURPOSES ONLY.
  14.  */
  15. UNSIGNED 
  16.    MASK[320]; /* MASK FOR HIDDEN LINE REMOVAL                     */
  17. INT 
  18.    H[65][65]; /* HEIGHT OR ELEVATION ABOVE SEA LEVEL              */
  19. UNSIGNED 
  20.    COLOR,     /* PIXEL COLOR                                      */
  21.    FMAX,      /* MAX. ELEVATION                                   */
  22.    SEED,      /* SEED FOR RANDOM NUMBER GENERATOR                 */
  23.    X;         /* DISTANCE ALONG X-AXIS                            */
  24. INT   
  25.    Z,         /* ELEVATION ABOVE SEA LEVEL                        */
  26.    ZP,        /* PREVIOUS ELEVATION ABOVE SEA LEVEL               */
  27.    ODD,       /* 1 FOR ODD NUMBERED CROSS-SECTIONS, 0 FOR EVEN    */
  28.    FIRST;     /* 1 IF FIRST POINT ON CROSS-SECTION, ELSE 0        */
  29.  
  30. /*============ ╞UNCTION: MAIN =====================================*/
  31. MAIN()
  32.   UNSIGNED I1, I2, J1, J2,   /* INDEXES FOR NODES AT CORNERS       */
  33.       DELTA,   /* DIFFERENCE IN INDEXES FOR NODES AT ENDS OF SIDE  */
  34.       IM, JM,  /* INDEXES OF NODE AT MIDPOINT OF SIDE              */
  35.       I,       /* CROSS-SECTION NUMBER                             */
  36.       J,       /* SEGMENT NUMBER                                   */
  37.       BX, BY,  /* X,Y COORDINATES OF BEGINNING OF LINE SEGMENT     */
  38.       EX, EY,  /* X,Y COORDINATES OF END OF LINE SEGMENT           */
  39.       N;       /* LOOP COUNTER                                     */
  40.   CHAR  *VPTR, ASEED[6], C, GETKEY();
  41.  
  42.   HIGHMEM(35840);
  43.   TEXTMODE(11, 1, 11);
  44.   PRINTF("%C%C%C", 147, 14, 5);
  45.   PRINTF("\N           ╞RACTAL ╠ANDSCAPES\N");
  46.   PRINTF("          ┴UTHOR: ╨AUL ├ARLSON\N\N\N");
  47.   PRINTF("╔T TAKES ABOUT ONE MINUTE TO COMPUTE THE");
  48.   PRINTF("ELEVATIONS FOR EACH LANDSCAPE.  ╫HEN A  ");
  49.   PRINTF("LANDSCAPE IS COMPLETE, PRESS ╥┼╘╒╥╬.\N\N\N\N");
  50.   PRINTF("        ╨RESS ANY KEY TO BEGIN...");
  51.   GETKEY();
  52.  
  53.   /*------- MAIN LOOP - LOOP UNTIL A ZERO SEED IS ENTERED --------*/
  54.  
  55.   WHILE (1)
  56.   █ 
  57.     TEXTMODE(11, 1, 11);
  58.     PRINTF("%C%C%C", 147, 14, 5);  
  59.     PRINTF("┼NTER SEED FOR RANDOM NUMBER GENERATOR\N");
  60.     PRINTF("   (1 TO 32767, OR 0 TO QUIT): ");
  61.     GETS(ASEED);
  62.     SEED = ATOI(ASEED);
  63.     IF (!SEED) BREAK;
  64.     SRANDOM(SEED);
  65.     PRINTF("\N├OMPUTING ELEVATIONS...");
  66.     FOR (N = 0; N < 320; N++) MASK[N] = 200;
  67.     
  68.     /*------------- COMPUTE HEIGHTS AT ALL NODES -----------------*/
  69.     
  70.     FMAX = 0;
  71.     FOR (DELTA = 64; DELTA >= 2; DELTA >>= 1)
  72.     █ J1 = 0;
  73.       FOR (J2 = DELTA; J2 <= 64; J1 += DELTA, J2 += DELTA)
  74.       █ I1 = 0;
  75.         JM = (J1 + J2)>>1;  /* GET MIDPOINT J INDEX */
  76.         FOR (I2 = DELTA; I2 <= 64; I1 += DELTA, I2 += DELTA)
  77.         █ IM = (I1 + I2)>>1;  /* GET MIDPOINT I INDEX */
  78.           H[J1][IM] = (H[J1][I1] + H[J1][I2]) / 2 + RANDM(DELTA);
  79.           H[J2][IM] = (H[J2][I1] + H[J2][I2]) / 2 + RANDM(DELTA);
  80.           IF (I1) /* IF NOT THE BOTTOM EDGE OF PLOT... */
  81.             H[JM][I1] = (H[J1][I1] + H[J2][I1]) / 2 + RANDM(DELTA);
  82.           H[JM][I2] = (H[J1][I2] + H[J2][I2]) / 2 + RANDM(DELTA);
  83.           IF (RANDOM() & 1)  /* PICK DIAGONAL RANDOMLY */
  84.             H[JM][IM] = (H[J1][I1] + H[J2][I2] + 3 * RANDM(DELTA))/2;
  85.           ELSE 
  86.             H[JM][IM] = (H[J2][I1] + H[J1][I2] + 3 * RANDM(DELTA))/2;
  87.         ▌
  88.       ▌
  89.     ▌
  90.     /*---------------- SMOOTH THE HEIGHTS -------------------------*/
  91.     
  92.     FOR (I = 0; I <= 64; I++)
  93.       FOR (J = 1; J < 64; J++)
  94.         H[J][I] = (H[J-1][I] + H[J][I] + H[J+1][I]) / 3;
  95.     
  96.     /*------------------- DRAW BORDER -----------------------------*/
  97.     HIRES(11, 1, 11);
  98.     FOR (N = 0; N < 317; N++) 
  99.     █ PIXEL(N, 0);
  100.       PIXEL(N, 198);
  101.     ▌
  102.     FOR (N = 0; N < 199; N++) 
  103.     █ PIXEL(0, N);
  104.       PIXEL(316, N);
  105.     ▌
  106.     
  107.     /*------ DISPLAY THE PLOT, REMOVING HIDDEN LINES --------------*/
  108.     
  109.     FOR (I = 0; I <= 64; I++)
  110.     █ ODD = 0;
  111.       FOR (N = 0; N < 2; N++)
  112.       █ ZP = 0;
  113.         FIRST = 1;
  114.         IF (I == 64 && ODD) BREAK;
  115.         FOR (J = 0; J < 64; J ++)
  116.         █ X = 5 * J;
  117.  
  118.           /*-------- INTERPOLATE TO GET HEIGHTS ON ODD SECTIONS -----
  119.                      AND ADJUST IF GOING INTO OR COMING OUT OF
  120.                      THE WATER.                                    */
  121.  
  122.           IF (J && J < 63 && I < 64)
  123.           █ IF (ODD) /* THEN INTERPOLATE */
  124.             █ IF (H[J-1][I] + H[J-1][I+1] > 0 &&       /* ENTERING */
  125.                   H[J][I] + H[J][I+1] < 0)             /*    WATER */
  126.                 X += 5 * (H[J][I] + H[J][I+1]) / 
  127.                         (H[J-1][I] + H[J-1][I+1] - 
  128.                              H[J][I] - H[J][I+1]);
  129.               ELSE
  130.                 IF (H[J+1][I] + H[J+1][I+1] > 0 &&      /* LEAVING */
  131.                     H[J][I] + H[J][I+1] < 0)            /*   WATER */
  132.                   X += 5 * (H[J][I] + H[J][I+1]) /
  133.                           (H[J][I] + H[J][I+1] - 
  134.                               H[J+1][I] - H[J+1][I+1]);
  135.             ▌
  136.             ELSE /* DON'T INTERPOLATE */
  137.             █ IF (H[J-1][I] > 0 && H[J][I] < 0)  /* ENTERING WATER */
  138.                 X += 5 * H[J][I] / (H[J-1][I] - H[J][I]);
  139.               ELSE 
  140.                 IF (H[J+1][I] > 0 && H[J][I] < 0) /* LEAVING WATER */
  141.                   X += 5 * H[J][I] / (H[J][I] - H[J+1][I]);
  142.             ▌
  143.           ▌
  144.           IF (ODD) Z = (H[J][I] + H[J][I+1]) / 2;
  145.           ELSE Z = H[J][I];
  146.  
  147.           /*------- SET ALL NEGATIVE HEIGHTS TO WATER LEVEL -------*/
  148.  
  149.           IF (Z < 0) Z = 0;
  150.           IF ((Z + ZP) == 0) COLOR = ╫┴╘┼╥;
  151.           ELSE COLOR = ╠┴╬─;
  152.           ZP = Z;
  153.  
  154.           /*-------- COMPUTE THE COORDINATES AND PLOT THE -----------
  155.                      LINE SEGMENT.                                 */
  156.  
  157.           EX = X;
  158.           EY = I + I + ODD + Z + 1;
  159.           IF (EY > FMAX) FMAX = EY;
  160.           IF (FIRST)
  161.           █ BX = EX = 1;
  162.             BY = EY;
  163.             FIRST = 0;
  164.           ▌
  165.           IF (I ▀▀ ODD) PLOT(BX, BY, EX, EY);
  166.           BX = EX; 
  167.           BY = EY;
  168.         ▌
  169.         IF (ODD) ODD = 0;
  170.         ELSE ODD = 1;
  171.       ▌
  172.     ▌
  173.     /*------ FILL IN SKY AND THEN WAIT UNTIL ╥┼╘╒╥╬ IS HIT ---------*/
  174.     /* REMOVE HIDDEN LINES UNTIL ABOVE MOUNTAINS */
  175.     COLOR = ╙╦┘;  
  176.     FOR (BY = 129; BY <= FMAX; BY ++) PLOT(1, BY, 315, BY);
  177.  
  178.     /* NOW USE A FAST FILL */
  179.     FOR (BY = 198 - FMAX; BY; BY--)
  180.     █   I = BY & 0XFFF8;
  181.         VPTR = 40960 + (I << 5) + (I << 3) + (BY & 7);
  182.         FOR (X = 0; X < 39; VPTR += 8, X++) *VPTR = 255;
  183.         *VPTR = 248;
  184.     ▌
  185.     WHILE ((C = GETKEY()) != 13);
  186.   ▌
  187.   TEXTMODE(6, 14, 14);
  188.   PRINTF("%C%C%C", 147, 142, 154);
  189.  
  190.  
  191. /* ╞UNCTION: PLOT 
  192.  *
  193.  *  ╘HIS FUNCTION PLOTS THE LINE SEGMENT(S) WITH HIDDEN LINE REMOVAL 
  194.  */
  195. PLOT(X1, Y1, X2, Y2)
  196. UNSIGNED X1, Y1, X2, Y2;
  197.   INT DX, DY, EI, ED, ER, IX, IY, T, SWAP;
  198.   
  199.   /*-------------- COMPUTE DELTA X AND DELTA Y --------------------*/
  200.  
  201.   Y1 = 199 - Y1;
  202.   Y2 = 199 - Y2;
  203.   DX = X2 - X1;
  204.   IF (Y1 < Y2)
  205.   █ T = Y2;
  206.     Y2 = Y1;
  207.     Y1 = T;
  208.     T = X2;
  209.     X2 = X1;
  210.     X1 = T;
  211.     IX = -1;
  212.   ▌
  213.   ELSE IX = 1;
  214.   DY = Y1 - Y2;
  215.   IY = -1;
  216.   SWAP = 0;
  217.   IF (DY > DX)
  218.   █ SWAP = 1;
  219.     T = DX;
  220.     DX = DY;
  221.     DY = T;
  222.   ▌
  223.   /*------------------ COMPUTE ERROR TERMS ------------------------*/
  224.   EI = DY<<1;                  
  225.   ED = (DY - DX)<<1;
  226.   ER = (DY<<1) - DX;
  227.  
  228.   /*------------------ PLOT THE LINE SEGMENT(S) -------------------*/
  229.   FOR (DX++; DX; DX--)
  230.   █ IF (Y1 < MASK[X1])
  231.     █ MASK[X1] = Y1;
  232.       SWITCH (COLOR)
  233.       █ CASE 1: IF (!ODD) PIXEL(X1, Y1);
  234.                 BREAK;
  235.         CASE 2: IF ((X1 & 1) == (Y1 & 1)) PIXEL(X1, Y1);
  236.                 BREAK;
  237.         CASE 3: PIXEL(X1, Y1);
  238.                 BREAK;
  239.       ▌
  240.     ▌
  241.     /*--------- UPDATE THE X OR Y COORDINATE AND ERROR TERM -------*/ 
  242.     IF (SWAP) Y1 += IY;
  243.     ELSE X1 += IX;
  244.     IF (ER < 0) ER += EI;
  245.     ELSE
  246.     █ ER += ED;
  247.       IF (SWAP) X1 += IX;
  248.       ELSE Y1 += IY;
  249.     ▌
  250.   ▌
  251.  
  252. /* ╞UNCTION: RANDM
  253.  *
  254.  *  ╘HIS FUNCTION RETURNS A RANDOM INTEGER IN THE RANGE
  255.  *  -DELTA+1 TO DELTA-1 INCLUSIVE.
  256.  */
  257. RANDM(DELTA)
  258. INT DELTA;
  259.   INT N;
  260.  
  261.   N = RANDOM() & (DELTA - 1);
  262.   RETURN(((RANDOM() & 255) < 127) ? -N : N);
  263.  
  264. /* ╞UNCTION: HIRES
  265.  *
  266.  * ╘HIS VERSION OF HIRES PUTS THE BITMAP UNDER ┬┴╙╔├ ╥╧═
  267.  * TO GET ENOUGH MEMORY AND STILL HAVE THE PROGRAM ╠╧┴─
  268.  * AND ╙┴╓┼ AS A ┬┴╙╔├ PROGRAM.
  269.  */
  270. HIRES(BACKGRND, FOREGRND, BORDER)
  271. CHAR BACKGRND, FOREGRND, BORDER;
  272.     CHAR COLOR, *PTR;
  273.  
  274.     PTR = 53280;
  275.     *PTR = BORDER;
  276.     COLOR = (FOREGRND << 4) ▀ BACKGRND;
  277.     FOR (PTR = 40960; PTR < 48960; PTR++) *PTR = 0;
  278.     FOR (PTR = 35840; PTR < 36840; PTR++) *PTR = COLOR;
  279.     PTR = 1;
  280.     *PTR = *PTR & 254;
  281.     PTR = 56576;
  282.     *PTR = (*PTR & 252) ▀ 1;
  283.     PTR = 53272;
  284.     *PTR = (*PTR & 15) ▀ 48;
  285.     *PTR = (*PTR & 240) ▀ 8;
  286.     PTR = 53265;
  287.     *PTR ▀= 32;
  288.     PTR = 648;
  289.     *PTR = 140;
  290.  
  291. /* ╞UNCTION: TEXTMODE
  292. */
  293. TEXTMODE(BACKGRND, FOREGRND, BORDER)
  294. CHAR BACKGRND, FOREGRND, BORDER;
  295.     CHAR *PTR;
  296.  
  297.     PTR = 1;
  298.     *PTR = *PTR ▀ 1;
  299.     PTR = 53280;
  300.     *PTR++ = BORDER;
  301.     *PTR = BACKGRND;
  302.     FOR (PTR = 1024; PTR < 2024; PTR++) *PTR = 32;
  303.     FOR (PTR = 55296; PTR < 56296; PTR++) *PTR = FOREGRND;
  304.     PTR = 56576;
  305.     *PTR = (*PTR & 252) ▀ 3;
  306.     PTR = 53265;
  307.     *PTR &= 223;
  308.     PTR = 53272;
  309.     *PTR = (*PTR & 15) ▀ 16;
  310.     *PTR = (*PTR & 240) ▀ 4;
  311.     PTR = 648;
  312.     *PTR = 4;
  313.  
  314. /* ╞UNCTION: PIXEL
  315.  *
  316.  * ╙ETS THE PIXEL AT X,Y
  317.  */
  318. PIXEL(X, Y)
  319. UNSIGNED X, Y;
  320.     CHAR *V;
  321.     UNSIGNED TMP;
  322.     STATIC CHAR BITVALS[] = █ 128, 64, 32, 16, 8, 4, 2, 1 ▌;
  323.  
  324.     TMP = Y & 0XFFF8;
  325.     V = 40960 + (TMP << 5) + (TMP << 3) + ((Y & 7) ▀ (X & 0XFFF8));
  326.     *V ▀= BITVALS[X & 7];
  327.  
  328. /* ╞UNCTION: GETKEY
  329.  *
  330.  * ╫AITS FOR AND RETURNS A KEYPRESS.
  331.  */
  332. CHAR GETKEY()
  333.     CHAR A, X, Y;
  334.  
  335.     A = 0;
  336.     WHILE (A == 0) SYS(0XF13E, &A, &X, &Y);
  337.     RETURN A;
  338.  
  339.